<?php
//namespace SP\Common;
class SP_Common_ClassLoader
{
	private $namespaces=array();
	private $libs_folder='/includes/libs';
	private $model_folder='/includes/model';
	private $outer_classes;
	private $doc_root;
	
	private function splitCamelCase($string, $lower = true)
	{
	  $array = preg_split('/([A-Z][^A-Z]*)/', $string, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
	  if ($lower) 
	  {
		$array = array_map(strtolower, $array);
	  }
	  return $array;
	}
	
	private function arrayToString($array, $glue=',', $outer='',$keys=false)
	{
		if(is_array($array))
		{
			if ($keys) $array=array_keys($array);
			if($outer=='')
			{
				return implode($glue,$array);
			}
			else
			{
				foreach($array as $value)
				{
					$str=$str.$outer.$value.$outer.$glue;
				}
				return self::delLastChar($str);
			}
		}
		else
		{
			return $array;
		}
	}
	
	function __construct()
	{
		$this->doc_root=$_SERVER['DOCUMENT_ROOT'];
	}
	
	/*
	Забиваем массив пространств имен, в котором 
	ключ ($nspace) - пространство имен,
	значение ($path) - путь к папке класса.
	Сюда же можно заносить путь к классам, находящимся
	в глобальном пространстве имен.
	*/
	public function setNamespace($nspace,$path)
	{
		$this->namespaces[$nspace]=$path;
	}
	
	/*
	Сразу захуяриваем в пространство имен массив
	*/
	public function setNamespaces(array $classes)
	{
		$this->namespaces = array_merge($this->namespaces, $classes);
	}
	
	/*
	Устанавливает папку (относительно корня сайта), в которой лежит фрэймворк.
	Например setLibsFolder('/includes/libs'), классы буду искаться в DOCUMENT_ROOT.'/includes/libs'
	Классы из глобального пространства имен ищем в этой папке
	*/
	public function setLibsFolder($path)
	{
		$this->libs_folder=$path;
	}
	
	
	/*
	Устанавливает папку (относительно корня сайта), в которой лежат классы моделей.
	Например setLibsFolder('/includes/model'), классы буду искаться в DOCUMENT_ROOT.'/includes/libs'
	Классы из глобального пространства имен ищем в этой папке
	*/
	public function setModelFolder($path)
	{
		$this->model_folder=$path;
	}
	
	//Устанавливает loadClass() вместо __autoload();
	public function init()
	{
		spl_autoload_register(array($this, 'loadClass'));
	}
	
	public function setRootDir($dir)
	{
		$this->doc_root=$dir;
	}
	
	public function loadClass($class)
	{
		if(false!==($pos=strpos($class,'\\')))
		{	
			$class_path=str_replace('\\', DIRECTORY_SEPARATOR, $class);
			$class_name=$this->doc_root.$this->libs_folder.$class_path.'.php';
			$class_name_lower=$this->doc_root.$this->libs_folder.strtolower($class_path).'.php';
			if(file_exists($class_name) && !is_dir($class_name))
			{
				return require_once($class_name);
			}
			elseif(file_exists($class_name_lower) && !is_dir($class_name_lower))
			{
				return require_once($class_name_lower);				
			}
			else
			{
				$path=$this->namespaces[substr($class,0,$pos)];					
				$class_name=$this->doc_root.$path.$class_path.'.php';
				$class_name_lower=$this->doc_root.$path.strtolower($class_path).'.php';
				if(file_exists($class_name) && !is_dir($class_name))
				{
					return require_once($class_name);
				}
				elseif(file_exists($class_name_lower) && !is_dir($class_name_lower))
				{
					return require_once($class_name_lower);				
				}
				else
				{
					return false;
				}
			}			
		}
		else
		{			
			$class_name_fromarr=$this->doc_root.$this->namespaces[$class];
			if(file_exists($class_name_fromarr) && !is_dir($class_name_fromarr))
			{
				return require_once($class_name_fromarr);				
			}
			elseif(false!==($pos=strpos($class,'_')))
			{
				$class_path = str_replace('_', '\\', $class);
				$this->loadClass($class_path);
			}
			elseif($array=$this->splitCamelCase($class))
			{
				$name=$this->arrayToString($array,'_');
				$model_name=$this->doc_root.$this->model_folder.'/'.$name.'.php';
				$base_model_name=$this->doc_root.$this->model_folder.'/base/'.$name.'.php';
				$doc_model_name=$this->doc_root.$this->model_folder.'/'.$class.'.php';
				$doc_base_model_name=$this->doc_root.$this->model_folder.'/generated/'.$class.'.php';
				if(file_exists($model_name) && !is_dir($model_name))
				{
					return require_once($model_name);
				}
				elseif(file_exists($base_model_name) && !is_dir($base_model_name))
				{
					return require_once($base_model_name);				
				}
				if(file_exists($doc_model_name) && !is_dir($doc_model_name))
				{
					return require_once($doc_model_name);
				}
				elseif(file_exists($doc_base_model_name) && !is_dir($doc_base_model_name))
				{
					return require_once($doc_base_model_name);				
				}
				else
				{
					return false;
				}
			}
			else
			{
				return false;
			}
		}
	}
	
}
?>
